package cn.micro.keep.accounts.common.utils;

import java.util.concurrent.atomic.AtomicLong;

public class UniqueCodeGenerator {
    private static final AtomicLong sequence = new AtomicLong();
    private static final String MACHINE_ID = "1234567890";
    private static final String TIMESTAMP_LEFT_PAD = "000000000";
    private static final String TIMESTAMP_RIGHT_PAD = "00000000";
    private static final String WORKER_ID_LEFT_PAD = "0000000";
    private static final String WORKER_ID_RIGHT_PAD = "00000";
    private static final String NODE_ID_LEFT_PAD = "0000";
    private static final String NODE_ID_RIGHT_PAD = "00";
    private static final int WORKER_ID_LENGTH = 5;
    private static final int NODE_ID_LENGTH = 2;
    private static final int TIMESTAMP_LENGTH = 8;

    public static void main(String[] args) {
        long uniqueCode = generateUniqueCode();
        System.out.println(uniqueCode);
    }

    private static long generateUniqueCode() {
        long timestamp = System.currentTimeMillis() / 1000;
        long sequenceValue = sequence.incrementAndGet();
        long machineId = Integer.parseInt(MACHINE_ID);
        long workerId = System.identityHashCode(UniqueCodeGenerator.class) % (1 << WORKER_ID_LENGTH);
        long nodeId = System.identityHashCode(UniqueCodeGenerator.class) % (1 << NODE_ID_LENGTH);
        return (timestamp << 24) | (sequenceValue & 0xFFFFFF) | (workerId << (TIMESTAMP_LENGTH + NODE_ID_LENGTH)) | (nodeId << TIMESTAMP_LENGTH)
                | (machineId & ((1 << WORKER_ID_LENGTH) - 1) << (TIMESTAMP_LENGTH + NODE_ID_LENGTH + WORKER_ID_LENGTH));
    }


    public static String generateUniqueCodeByLen(int len){
        String code = String.valueOf(generateUniqueCode());
        return code.substring(0,len);
    }
}
